package sanrenxing.ForePaper.servlet;

import com.google.gson.Gson;
import sanrenxing.ForePaper.dao.ForePaperDao;
import sanrenxing.ForePaper.dao.impl.ForePaperDaoImpl;
import sanrenxing.ForePaper.domain.ExamScore;
import sanrenxing.ForePaper.domain.ExamSubject;
import sanrenxing.ForePaper.domain.PaperStateMsg;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.swing.plaf.basic.BasicScrollPaneUI;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Administrator
 * @date 2020/10/5 19:03
 * 编辑者：邓志强
 * 功能：
 */
@WebServlet("/ExamsPageServlet")
public class ExamsPageServlet extends HttpServlet {
    //创建业务层对象
    ForePaperDao fpd=new ForePaperDaoImpl();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求字符集
        req.setCharacterEncoding("utf-8");
        //设置响应字符集和内容类型
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");

        //接收方法名称
        String method=req.getParameter("method");
        if (method.equals("showExamsSubject")){
            this.showExamsSubject(req,resp);
        }else if (method.equals("showState")){//检查是否有考试的方法
            this.showState(req,resp);
        }else if (method.equals("updateState")){//进入考试的时候更改学员考试状态有代考改为在考方法
            this.updateState(req,resp);
        }else if (method.equals("deleteState")){//自动阅卷的时候删除学员考试状态
            this.deleteState(req,resp);
        }else if (method.equals("checkState")){//检查学员是否有考试状态
            this.checkState(req,resp);
        }else if (method.equals("addScore")){//自动阅卷完成后添加成绩信息
            this.addScore(req,resp);
        }else if (method.equals("addReexams")){//添加补考信息
            this.addReexams(req,resp);
        }else if (method.equals("addSubAnalysis")){//添加难易程度信息
            this.addSubAnalysis(req,resp);
        }
    }

    /**
     * 添加难易程度信息
     * @param req
     * @param resp
     */
    private void addSubAnalysis(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //创建输出流对象
        PrintWriter out=resp.getWriter();
        //接收来自客户端的信息(在考/不在考),在考试状态表中拿到对应的状态编号
        int conditionId=Integer.parseInt(req.getParameter("conditionId"));
        //接收来自客户端的信息(正确答案)，拿到对应试卷的正确答案编号字符串组
        String correctId=req.getParameter("correctId");
        //添加对应试卷的50个题目的初始难易程度的数据，并传入刚刚获取到的状态编号
        fpd.initializeAnalysis(conditionId);
        //调用查询班级学员人数的方法，并传入获取到的状态编号，定义变量保存
        int stuNum=fpd.findStuNum(conditionId);
        //定义一个strs保存正确答案的字符串数组
        String[] strs=null;
        //判断用户正确答案编号字符串的长度不等于0
        if (correctId.length()!=0){
            //通过分割“,”将学员的正确答案字符串转换为字符串数组，并去掉最后一个逗号
            strs=correctId.substring(0,correctId.length()-1).split(",");
            //通过foreach遍历正确答案
            for (String str:strs) {
                //调用方法更新难易程度表，并且传入状态编号，正确答案，和学员数量
                fpd.updateAnalysis(conditionId,str,stuNum);
            }
        }
    }

    /**
     * 添加补考信息
     * @param req
     * @param resp
     */
    private void addReexams(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //创建输出流
        PrintWriter out=resp.getWriter();
        //接收来自客户端的信息,考试的状态编号
        int conditionId=Integer.parseInt(req.getParameter("conditionId"));
        //调用业务层方法，获得查询到的补考信息，定义一个map集合接收，传参状态编号
        Map<String,Object> map=fpd.findReexams(conditionId);
        //调用业务层方法，添加补考信息，传参map集合中的学员编号和课程编号
        fpd.addReexams((String)map.get("stuId"),(int)map.get("courseId"));
    }

    /**
     * 自动阅卷完成后添加成绩信息
     * @param req
     * @param resp
     */
    private void addScore(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //创建输出流
        PrintWriter out=resp.getWriter();
        //创建session对象
        HttpSession session=req.getSession();
        //通过session对象获取学员编号
        String stuId=(String) session.getAttribute("stuId");
        //接收来自客户端的状态编号信息
        int conditionId=Integer.parseInt(req.getParameter("conditionId"));
        //接收来自客户端的分数
        int score=Integer.parseInt(req.getParameter("score"));
        //调用业务层方法，查询到的属于一个学生成绩，定义考试成绩对象接收，传入状态编号以及分数
        ExamScore examScore=fpd.findScore(conditionId,score);
        //调用业务层方法,添加学员考试成绩信息，传参考试成绩对象
        fpd.addExamScore(examScore);
    }

    /**
     * 检查学员是否有考试状态
     * @param req
     * @param resp
     * @throws IOException
     */
    private void checkState(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //创建输出流
        PrintWriter out=resp.getWriter();
        //创建session对象
        HttpSession session=req.getSession();
        //获取学员编号
        String stuId=(String) session.getAttribute("stuId");
        //创建业务层对象
        ForePaperDao fpd=new ForePaperDaoImpl();
        //调用业务层方法检查该学员是否有考试状态，传参学员编号,返回布尔值
        Boolean boo=fpd.checkState(stuId);
        //判断发送状态
        if (boo){
            out.print("ok");
        }else{
            out.print("no");
        }
    }

    /**
     * 显示考试题目
     * @param req
     * @param resp
     */
    private void showExamsSubject(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //创建输出流对象
        PrintWriter out=resp.getWriter();
        //创建session
        HttpSession session=req.getSession();
        //通过session对象获取学员编号
        String stuId=(String) session.getAttribute("stuId");
        //通过业务层对象调用题目数量方法，传参学员编号，定义map集合接收
        Map<String,Object> map=fpd.subjectNum(stuId);
        //从map集合中取出题目编号组，定义字符串变量接收
        String subjectIds=(String) map.get("subjectIds");
        //将题目编号组通过字符串分割",",并且定义字符串数组接收
        String[] arrs=subjectIds.split(",");
        //创建一个保存五十个题目的Array集合，泛型是考试题目对象
        List<ExamSubject> examSubjectList =new ArrayList<>();;
        //通过foreach遍历分割好的题目数组
        for (String arr:arrs) {
            //调用数据层获得题目方法,将遍历的题号传参，获得的返回值add到上方定义的数组当中
            examSubjectList.add(fpd.getSubject(arr));
        }
        //通过Collections的shuffle方法打乱题目顺序，传参题目数组
        Collections.shuffle(examSubjectList);
        //从map中获取结束时间
        String finishTime=(String) map.get("finishTime");
        //从map中获取考试状态编号
        String conditionId=(String) map.get("conditionId");
        //创建map集合
        Map<String,Object> map1=new HashMap<>();
        //将数据保存到map集合当中
        //在map集合中定义名字为data，保存打乱后的题目数组
        map1.put("data", examSubjectList);
        //保存结束时间
        map1.put("finishTime",finishTime);
        //保存状态编号
        map1.put("conditionId",conditionId);
        //创建gson对象
        Gson gson=new Gson();
        //将map集合转换（序列化）为json
        String json=gson.toJson(map1);
        //发送数据
        out.print(json);
    }


    /**
     * 自动阅卷的时候删除学员考试状态
     * @param req
     * @param resp
     */
    private void deleteState(HttpServletRequest req, HttpServletResponse resp) {
        //接收来自客户端发送的考试状态编号
        int conditionId=Integer.parseInt(req.getParameter("conditionId"));
        //调用业务层方法，删除状态，传参状态编号
        fpd.deleteState(conditionId);
    }

    /**
     * //更改学员考试状态有代考改为在考方法
     * @param req
     * @param resp
     */
    private void updateState(HttpServletRequest req, HttpServletResponse resp) {
        //接收来自客户端发送的考试状态编号
        int conditionId=Integer.parseInt(req.getParameter("conditionId"));
        //调用业务层方法,修改状态，传参考试状态编号
        fpd.updateState(conditionId);
    }

    /**
     * 展示前端学员考试状态及考试信息方法
     * @param req
     * @param resp
     */
    private void showState(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        //创建输出流
        PrintWriter out=resp.getWriter();
        //创建session，获取学员编号对象
        HttpSession session=req.getSession();
        //通过session对象获取学员编号
        String stuId=(String) session.getAttribute("stuId");
        //调用业务层展示状态方法，传参学员编号，定义试卷状态信息类接收
        PaperStateMsg paperStateMsg=fpd.showState(stuId);
        //判断试卷状态信息是否为空
        if (paperStateMsg!=null){
            //创建gson对象用于序列化对象
            Gson gson=new Gson();
            //序列化为json字符串，传参考试状态信息变量
            String json=gson.toJson(paperStateMsg);
            //发送数据
            out.print(json);
        }else{
            out.print("no");
        }
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}
